package com.itheima.springbootwebtlias.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/*
  通知类型的特点
 */
@Slf4j
//@Component
//@Aspect  //1.编写切面类
public class AspectType {

    //spring提供抽取公共的切入点表达式的注解：@PointCut
    @Pointcut("execution(* com.itheima.springbootwebtlias.controller.DeptController.QueryAll(..))")
    //公共的切入点表达式，可以在外部的其他的切面类中使用
    public void kk(){}  //公共的，无返回值的，无参数的，无具体代码的

    //私有的切入点表达式，只能在当前类中使用
    //private void kk(){}  //公共的，无返回值的，无参数的，无具体代码的


    //2.编写通知方法：前置通知
    @Before("kk()")  //3. 通知类型  +  切入表达式
    public void before() throws Throwable {
        log.info("before前置通知... ...");
    }

    @After("kk()")  //3. 通知类型  +  切入表达式
    public void after(){
        log.info("after后置通知... ...");
    }

    @AfterReturning("kk()")  //3. 通知类型  +  切入表达式
    public void afterReturning(){
        log.info("afterReturning返回后通知... ...");
    }

    @AfterThrowing("kk()")  //3. 通知类型  +  切入表达式
    public void afterThrowing(){
        log.info("afterThrowing异常后通知... ...");
    }


    //环绕通知：功能最强大的通知类型
    @Around("kk()")  //3. 通知类型  +  切入表达式
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
       //自行调用目标方法：
        Object proceed = null;
        try {
            log.info("around...before前置通知... ...");
            proceed = pjp.proceed();
            log.info("around...afterReturning返回后通知... ...");
        } catch (Throwable e) {
            log.info("around...afterThrowing异常后通知... ...");
            throw new RuntimeException(e);
        } finally {
            log.info("around...after后置通知... ...");
        }
        return proceed;
    }
}
